fix(langgraph): carry ToolMessage.error onto the LangChain status flag - #2263
Conversation
Both langgraph adapters dropped AG-UI's ToolMessage.error when converting an incoming tool message to a LangChain ToolMessage. LangChain has a status field (success/error) for this, and providers such as langchain_anthropic map it onto the model's tool-result flag. With the field dropped, a client-reported tool failure reached the model as a success. The impact is provider-dependent, so it was invisible on Gemini. Map error onto status in both adapters (TypeScript and Python): status is error when the AG-UI error field is set, else success. A test is added on each side. Scope: the status flag only. Preserving the error text and round-tripping it back to the client are separate questions raised in the issue and left out here. Fixes ag-ui-protocol#2226
Python Preview PackagesVersion
Install with uvAdd the TestPyPI index to your [[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
explicit = trueThen install the packages you need: # Core SDK
uv add 'ag-ui-protocol==0.0.0.dev1785306123' --index testpypi
# Integrations (each already depends on the matching ag-ui-protocol preview)
uv add 'ag-ui-langgraph==0.0.0.dev1785306123' --index testpypi
uv add 'ag-ui-crewai==0.0.0.dev1785306123' --index testpypi
# NOTE: ag-ui-agent-spec depends on pyagentspec (git-only, not on PyPI).
# You will need to install pyagentspec separately from its git repo.
uv add 'ag-ui-agent-spec==0.0.0.dev1785306123' --index testpypi
uv add 'ag_ui_adk==0.0.0.dev1785306123' --index testpypi
uv add 'ag_ui_strands==0.0.0.dev1785306123' --index testpypiInstall with pippip install \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
ag-ui-protocol==0.0.0.dev1785306123
Commit: e8a4ba0 |
|
Reviewed and verified locally against the PR head.
The fix is correct, minimal, and tested on both sides. I've filed the two carve-outs so the scope of this PR is recorded and the remaining work isn't lost:
On the "should the |
@ag-ui/a2a-middleware
@ag-ui/a2ui-middleware
@ag-ui/event-throttle-middleware
@ag-ui/mcp-apps-middleware
@ag-ui/mcp-middleware
@ag-ui/a2a
@ag-ui/adk
@ag-ui/ag2
@ag-ui/agno
@ag-ui/aws-strands
@ag-ui/crewai
@ag-ui/langchain
@ag-ui/claude-agent-sdk
@ag-ui/langgraph
@ag-ui/llamaindex
@ag-ui/mastra
@ag-ui/pydantic-ai
@ag-ui/vercel-ai-sdk
@ag-ui/watsonx
@ag-ui/a2ui-toolkit
create-ag-ui-app
@ag-ui/client
@ag-ui/core
@ag-ui/encoder
@ag-ui/proto
commit: |
contextablemark
left a comment
There was a problem hiding this comment.
Looks good. Created some follow-on issues.
….error The reverse conversion (langchainMessagesToAgui / langchain_messages_to_agui) dropped the LangChain tool result status, so a status='error' tool message came back to the client with error unset. After #2263 fixed the forward direction, a client whose message list seeds the next run (fresh thread, stateless replay, snapshot-then-resend) re-converted with error unset and silently produced status='success' again, undoing the fix. Map status == 'error' back onto AG-UI's error in both adapters. The forward direction is flag-only, so the original text is not recoverable here; error carries a fixed sentinel so a client can tell a reported failure apart from a reported failure text. Flag durable, text best-effort, per the standard agreed on #2306. A test is added on each side. Fixes #2305
…in four more adapters The same one-line omission fixed for LangGraph in #2263 is present in several other first-party adapters: AG-UI's ToolMessage.error is not read when an incoming tool result is converted into the target framework's tool-result shape, so a client-reported tool failure is handed to the model as a success. Per the standard agreed on #2306, set the framework's error flag from bool(error) (flag only; text is not folded because every target here has a dedicated flag): langchain/typescript ToolMessage status (verbatim #2263); aws-strands/python Bedrock toolResult status (was pinned to success); vercel-ai-sdk/typescript AI SDK v4 tool-result isError; mastra/typescript AI SDK v4 tool-result isError. Both vercel-ai-sdk and mastra resolve AI SDK v4, whose ToolResultPart already carries isError; no version gate is needed. Also fix aws-strands _build_snapshot_messages, an AG-UI to AG-UI rebuild of the client's own messages: it dropped the client's error and encrypted_value on the snapshot echo. Copy both through. A test is added next to each adapter's conversion tests. Fixes #2306
Fixes #2226.
Problem
Both langgraph adapters drop AG-UI's
ToolMessage.errorwhen they convert an incoming tool message to a LangChainToolMessage. LangChain has astatusfield ("success" | "error") for exactly this, and providers such aslangchain_anthropicmap it onto the model's tool-result flag. With the field dropped, a client-reported tool failure reaches the model as a success. The impact is provider-dependent, so it is invisible on Gemini and shows up on Anthropic.Fix
Map
errorontostatusin both adapters:"error"when the AG-UIerrorfield is set, else"success".integrations/langgraph/typescript/src/utils.ts, thetoolbranch ofaguiMessagesToLangChain. The langgraph-sdkToolMessagetype already typesstatus?: "error" | "success".integrations/langgraph/python/ag_ui_langgraph/utils.py, thetoolbranch ofagui_messages_to_langchain.The AG-UI
ToolMessageschema already haserrorin both languages, so no type changes are needed.Scope
This PR maps the flag only. The two open questions from the issue — preserving the
errortext and round-tripping it back to the client — look like a separate protocol topic and are left out here.Tests
A test is added on each side, next to the existing tool-message conversion tests.
message-conversion.test.ts— full package suite green, 265 tests.test_message_conversion.py—unittest discover testsgreen, 43 tests.